import fs from 'node:fs'
import path from 'node:path'
import os from 'node:os'
import {styleText} from 'node:util'

class LogLevel {
    public static readonly INFO = 'INFO'
    public static readonly WARN = 'WARN'
    public static readonly ERROR = 'ERROR'
}

class Logger {
    private logStream: fs.WriteStream
    public consoleDisplay = true

    constructor(filepath: string, consoleDisplay: boolean = true) {
        const resolvedPath = path.resolve(process.cwd(), filepath)
        this.ensureDirectoryExists(resolvedPath)
        this.logStream = fs.createWriteStream(resolvedPath, {flags: 'a'})
        this.logStream.on('error', (error) => {
            console.error('Logger error:', error)
        })
        this.consoleDisplay = consoleDisplay
    }

    private ensureDirectoryExists(filepath: string) {
        const dir = path.dirname(filepath)
        if (!fs.existsSync(dir)) {
            fs.mkdirSync(dir, {recursive: true})
        }
    }

    public info(msg: string) {
        this.log(LogLevel.INFO, msg)
    }

    public warning(msg: string) {
        this.log(LogLevel.WARN, msg)
    }

    public error(msg: string) {
        this.log(LogLevel.ERROR, msg)
    }

    private log(level: string, msg: string) {
        const logMessage = `[${level}] ${this.datetime()} ${msg}${os.EOL}`
        this.logStream.write(logMessage)
        if (this.consoleDisplay) {
            const levelColor = level === LogLevel.INFO ? 'blue' : level === LogLevel.WARN ? 'yellow' : 'red'
            const dateTimeColor = 'green'
            const logMessageColored = `${styleText(levelColor, `[${level}]`)} ${styleText(dateTimeColor, this.datetime())} ${msg}`
            console[level === LogLevel.INFO ? 'log' : level === LogLevel.WARN ? 'warn' : 'error'](logMessageColored)
        }
    }

    private datetime(): string {
        const now = new Date()
        const year = now.getFullYear()
        const month = now.getMonth() + 1
        const day = now.getDate()
        const hour = now.getHours()
        const minute = now.getMinutes()
        const second = now.getSeconds()

        return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}`
    }

    public close() {
        this.logStream.close()
    }
}

export default Logger